package org.ym.database.hibernate.query;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.ym.tools.StringTool;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class FilterCollector {
    public static final String POINT = ".";
    /**
     * 查询条件集合
     */
    List<Filter> filterList = new ArrayList<>();

    /**
     * 添加查询条件
     * @param field 字段名
     * @param value 值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    FilterCollector addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, String value) {
        filterList.add(new Filter.FilterBuilder<String>().key(field).value(value).queryOperateSymbol(queryOperateSymbol).build());
        return this;
    }

    /**
     * 添加查询条件
     * @param field 字段名
     * @param value 值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    FilterCollector addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, Number value) {
        filterList.add(new Filter.FilterBuilder<Number>().key(field).value(value).queryOperateSymbol(queryOperateSymbol).build());
        return this;
    }


    /**
     * 添加查询条件
     * @param field 字段名
     * @param value 值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    FilterCollector addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, Date value) {
        filterList.add(new Filter.FilterBuilder<Date>().key(field).value(value).queryOperateSymbol(queryOperateSymbol).build());
        return this;
    }

    /**
     * 添加查询条件
     * @param field 字段名
     * @param value 值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    FilterCollector addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, boolean value) {
        filterList.add(new Filter.FilterBuilder<Boolean>().key(field).value(value).queryOperateSymbol(queryOperateSymbol).build());
        return this;
    }

    /**
     * between条件
     * @param field 字段
     * @param start 起始
     * @param end 结束
     * @return 当前对象
     */
    FilterCollector between(String field, Date start, Date end){
        filterList.add(new Filter.FilterBuilder<Date>().key(field).value(start).endValue(end).queryOperateSymbol(QueryOperateSymbolEnum.BETWEEN).build());
        return this;
    }

    /**
     * between条件
     * @param field 字段
     * @param start 起始
     * @param end 结束
     * @return 当前对象
     */
    FilterCollector between(String field, Number start, Number end){
        filterList.add(new Filter.FilterBuilder<Number>().key(field).value(start).endValue(end).queryOperateSymbol(QueryOperateSymbolEnum.BETWEEN).build());
        return this;
    }

    /**
     * 判断字段是否为空
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector isNull(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.NULL).build());
        return this;
    }

    /**
     * 判断字段是否为空
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector isNotNull(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.NOT_NULL).build());
        return this;
    }

    /**
     * in查询
     * @param field 字段
     * @param array 数组
     * @return 当前对象
     */
    <T> FilterCollector in(String field,T[] array){
        filterList.add(new Filter.FilterBuilder<T[]>().key(field).value(array).queryOperateSymbol(QueryOperateSymbolEnum.IN).build());
        return this;
    }

    /**
     * notIn查询
     * @param field 字段
     * @param array 数组
     * @return 当前对象
     */
    <T> FilterCollector notIn(String field,T[] array){
        filterList.add(new Filter.FilterBuilder<T[]>().key(field).value(array).queryOperateSymbol(QueryOperateSymbolEnum.NOT_IN).build());
        return this;
    }

    /**
     * in查询
     * @param field 字段
     * @param list 集合
     * @return 当前对象
     */
    <T> FilterCollector in(String field,List<T> list){
        filterList.add(new Filter.FilterBuilder<List<T>>().key(field).value(list).queryOperateSymbol(QueryOperateSymbolEnum.IN).build());
        return this;
    }

    /**
     * notIn查询
     * @param field 字段
     * @param list 集合
     * @return 当前对象
     */
    <T> FilterCollector notIn(String field,List<T> list){
        filterList.add(new Filter.FilterBuilder<List<T>>().key(field).value(list).queryOperateSymbol(QueryOperateSymbolEnum.NOT_IN).build());
        return this;
    }

    /**
     * count
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector count(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.COUNT).build());
        return this;
    }

    /**
     * sum
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector sum(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.SUM).build());
        return this;
    }

    /**
     * max
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector max(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.MAX).build());
        return this;
    }

    /**
     * min
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector min(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.MIN).build());
        return this;
    }

    /**
     * average
     * @param field 字段
     * @return 当前对象
     */
    FilterCollector average(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.AVERAGE).build());
        return this;
    }

    /**
     * 分组
     * @param field
     * @return
     */
    FilterCollector group(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.GROUP).build());
        return this;
    }

    /**
     * 添加字段
     * @param field
     * @return
     */
    FilterCollector addFiled(String field){
        filterList.add(new Filter.FilterBuilder<Object>().key(field).queryOperateSymbol(QueryOperateSymbolEnum.ADD_FIELD).build());
        return this;
    }

    /**
     * 生成predicate
     * @param root 当前表
     * @param criteriaBuilder 查询
     * @return predicate
     */
    List<Predicate> generatePredicate(Root root, CriteriaBuilder criteriaBuilder){
        List<Predicate> predicateList = new ArrayList<>();
        Predicate predicate = null;
        for(Filter filter : filterList){
            predicate = filter.generatePredicate(root,criteriaBuilder);
            if(predicate != null){
                predicateList.add(predicate);
            }
        }
        return predicateList;
    }

    /**
     * 生成predicate
     * @param join join表
     * @param criteriaBuilder 查询
     * @return predicate
     */
    List<Predicate> generatePredicate(Join join, CriteriaBuilder criteriaBuilder){
        List<Predicate> predicateList = new ArrayList<>();
        Predicate predicate = null;
        for(Filter filter : filterList){
            predicate = filter.generatePredicate(join,criteriaBuilder);
            if(predicate != null){
                predicateList.add(predicate);
            }
        }
        return predicateList;
    }

    /**
     * 生成Expression
     *
     * @param root            当前表
     * @param criteriaBuilder 查询
     * @return Expression集合
     */
    List<Expression> generateExpression(Root root, CriteriaBuilder criteriaBuilder) {
        List<Expression> list = new ArrayList<>();
        Expression expression = null;
        for(Filter filter : filterList){
            expression = filter.generateExpression(root,criteriaBuilder);
            if(expression != null){
                list.add(expression);
            }
        }
        return list;
    }

    /**
     * 生成Expression
     *
     * @param join            联查表
     * @param criteriaBuilder 查询
     * @return Expression集合
     */
    List<Expression> generateExpression(Join join, CriteriaBuilder criteriaBuilder) {
        List<Expression> list = new ArrayList<>();
        Expression expression = null;
        for(Filter filter : filterList){
            expression = filter.generateExpression(join,criteriaBuilder);
            if(expression != null){
                list.add(expression);
            }
        }
        return list;
    }

    /**
     * 判断当前是否为空
     * @return
     */
    public boolean isEmpty(){
        return filterList.isEmpty();
    }

    /**
     * 清空查询
     * @return 当前对象
     */
    public FilterCollector clear(){
        filterList.clear();
        return this;
    }

    /**
     * 获取hashmap的key值
     * @return 字段key集合
     */
    public List<String> toDisplayKey(){
        return toDisplayKey(null);
    }

    /**
     * 获取hashmap的key值
     * @param joinKey 关联表
     * @return 字段key集合
     */
    public List<String> toDisplayKey(JoinKey joinKey){
        List<String> list = new ArrayList<>(filterList.size()/3*4);
        if(!filterList.isEmpty()){
            for(Filter filter : filterList){
                if(joinKey == null){
                    list.add(filter.getDisplayKey());
                }else{
                    list.add(StringTool.concatStr(joinKey.getDisplayKey(), POINT,filter.getDisplayKey()));
                }
            }
        }
        return list;
    }
}
